Skip to content

Fix APP14 markers#135

Open
jonnyawsom3 wants to merge 1 commit intogoogle:mainfrom
jonnyawsom3:APP14
Open

Fix APP14 markers#135
jonnyawsom3 wants to merge 1 commit intogoogle:mainfrom
jonnyawsom3:APP14

Conversation

@jonnyawsom3
Copy link
Contributor

@jonnyawsom3 jonnyawsom3 commented Jun 3, 2025

The APP14 tag is now added to RGB(XYB), CMYK and YCCK JPEGs, as it is required by some decoders.

Fixes libjxl/libjxl#3512

@dclunie
Copy link

dclunie commented Feb 24, 2026

This may be a stupid question, but XYB != RGB, so how is setting APP14 = RGB valid (as distinct from creating a new value for APP14 Transform flag, +/- the agreement of Adobe and/or SO/IEC JTC 1/SC 29/WG 1)?

I.e., how does a decoder distinguish between components that really are RGB, as distinct from being your new XYZ (even if neither is YCbCr)?

We create RGB (no color conversion) JPEGs all the time, which long pre-date the existence of XYZ, and insert APP14 accordingly.

@jonnyawsom3
Copy link
Contributor Author

The marker indicates the type of JPEG, not the contained colorspace. YCbCr is a lossy conversion, so we need to use RGB encoding to store the XYB accurately. Colorspace is handled by the ICC.

@dclunie
Copy link

dclunie commented Feb 24, 2026

I had always understood the "color transform" field in the APP14 marker to indicate what each of the three (or four) components (channels) "mean".

I.e., RGB is red, green, blue, XYZ are the three CIEXYZ tristimulus components which are most definitely not red, green or blue. It is true that CIEXYZ is also a "color space" (in the sense that sRGB or Adobe RGB are "color spaces" and could be described by ICC profiles), but XYZ is still not RGB.

I grant you that ITU T.872 (ISO 10918-6) 6.5.3 says "0 =- ... RGB for images that are encoded with three components", but that conflicts with the explicitly described value of 1, which is also 3 components. It is interesting that this statement is buried in a "printing" extension to JPEG, but it is nice that they call attention to the marker segment in a standard document, although it might have been better not to mention "RGB" at all. Adobe's documentation of APP14, such as it is, in "Supporting the DCT Filters in PostScript Level 2 - Technical Note #5116" isn't very specific about the value of this field, but seems to imply that 0 means no color transform applied (and to me, XYZ is a "transform" from RGB), but it does also separately describe color space related matters (e.g., for Rec 709).

So I guess that you are taking the position that APP14 "color transform" = 0 is no more and no less than a "not YCbCr" flag (for three component data), and that YCbCr, unlike all other three component transforms, is specified by this flag (or the JFIF header) and not the color space (e.g., an sRGB ICC profile would apply to either RGB or YCbCR component data), and that all other transforms (like XYZ or Lab or YUV) would instead by specified only by the color space, since there seems to be no other means of communicating any other "meaning" for the components.

@jonnyawsom3
Copy link
Contributor Author

YCbCr JPEG and RGB JPEG are fundamentally different encoding formats. Most decoders assume a JPEG is encoded in YCbCr space, usually with an ICC for P3, AdobeRGB, ect. The APP14 marker signals that it isn't YCbCr internally and that the application should treat it as RGB data, then color managed with the ICC into the correct color space.

It's a difference between colorspace and color format.

@dclunie
Copy link

dclunie commented Feb 24, 2026

I agree about what decoders may "assume".

But I assert that XYZ or XYB are different color "formats" ("models"?) too, in addition to being different color spaces, and should be described as such, since the components (channels) have a different meaning (no more and no less than Y, Cb and Cr, in the special case of historical JPEG YCbCr transformations).

I suppose though, that as long as the numerical values expected as input to the transformations in the ICC profile are unambiguously defined, this is a moot point.

Putting aside the chrominance downsampling typically used with YCbCr, if one had a YCbCr ICC profile specific to the JPEG numeric value range, and one wanted to leave the meaning of the three components to the color space definition, then one would not need to consider YCbCr as a special case, but could instead have a "YCbCr sRGB profile" (or a "YCbCr Rec 709 profile", as distinct from, say a "linear RGB Rec 709 profile"). I.e., pre-coordinating the component meaning ("color format") with the "color space". Not that I am suggesting that is a good idea.

@sboukortt
Copy link
Contributor

I.e., RGB is red, green, blue, XYZ are the three CIEXYZ tristimulus components which are most definitely not red, green or blue.

Why not? Do you agree that ProPhoto RGB is RGB?

@dclunie
Copy link

dclunie commented Feb 24, 2026

Not sure how those two questions are related, since AFAIK:

  • in ProPhoto RGB (ROMM RGB), there are three components defined and they are explicitly red, green and blue
  • in CIEXYZ, there are three components defined, and they are not simply red, green and blue, but rather X being (related to) red, Y being luminance, and Z being (related to) blue
  • in XYB, there are three components defined, and they are not red, green and blue per se, but rather correspond to LMS (long, medium and short wavelength sensitive cone) values

Are you arguing that LMS is essentially equivalent to RGB in terms of component labelling in a "color format", considering where the cone sensitivity functions lie on the spectrum and their order?

Sorry I introduced XYZ, rather than just XYB into the discussion, since it probably just confuses things.

@sboukortt
Copy link
Contributor

sboukortt commented Feb 24, 2026

  • in ProPhoto RGB (ROMM RGB), there are three components defined and they are explicitly red, green and blue
  • in CIEXYZ, there are three components defined, and they are not simply red, green and blue, but rather X being (related to) red, Y being luminance, and Z being (related to) blue

sRGB (which I imagine everyone will agree is RGB) has its components defined as:

  • first: X=0.4124, Y=0.2126, Z=0.0193
  • second: X=0.3576, Y=0.7152, Z=0.1192
  • third: X=0.1805, Y=0.0722, Z=0.9505

In ProPhoto RGB:

  • first component: X=0.79767, Y=0.28804, Z=0
  • second component: X=0.13519, Y=0.71188, Z=0
  • third component: X=0.03134, Y=0.00009, Z=0.82489

And XYZ, tautologically, can be described as:

  • first component: X=1, Y=0, Z=0
  • second component: X=0, Y=1, Z=0
  • third component: X=0, Y=0, Z=1

To me, the difference here seems more quantitative than qualitative. As far as I’m aware, the main argument against XYZ being RGB is that its primaries are not physically realisable, but that’s famously also true of ProPhoto RGB’s “green” and “blue”: https://en.wikipedia.org/wiki/File:CIExy1931_ProPhoto.svg

Regarding XYB (which is not CIE), LMS is more of an internal detail; a matrix is applied to it (X ∝ L−M, Y ∝ L + M, B ∝ S) that makes the resulting components a bit more RGB-like (almost reminiscent of CIE RGB, incidentally).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Adobe APP14 tag to JPEG images with specific colorspaces (fix XYB appearance in most apps)

3 participants